'''
Created on 2009-10-22

@author: summit
'''

from enthought.traits import api as traits
from enthought.tvtk.api import tvtk

######################################################################
# Utility functions.
######################################################################
def deref_itk(obj):
    """Dereferences the VTK object from the object if possible."""
    if isinstance(obj, titkbase):
        return obj._obj
    else:
        return obj


class titkbase(traits.HasTraits):
    '''
    classdocs
    '''
    # This is just a dummy integer (MUST be > 1) that indicates that
    # we are updating the traits and there is no need to change the
    # underlying VTK object.
    DOING_UPDATE = 10
    
    _obj = traits.Any
    
    # Stores the name of the traits that need to updated
    _updateable_traits_ = traits.Tuple
    
    # List of trait names that are to be included in the full traits view of this object.
    _full_traitnames_list_ = traits.List
    
    def __init__(self, tclass, object=None, update=True, **traits):
        '''Object initialization.
        
        Parameters
        ----------
        - obj: `vtkPythonDataManage` (default: None)
          An optional VTK object.  If passed the passed object is
          wrapped.  This defaults to `None` where a new VTK instance
          of class, `klass` is created.
        - update: `bool` (default: True)

          If True (default), the traits of the class are automatically
          updated based on the state of the wrapped VTK object.  If
          False, no updation is performed.  This is particularly
          useful when the object is being unpickled.

        - traits: `dict`

          A dictionary having the names of the traits as its keys.
          This allows a user to set the traits of the object while
          creating the object.
        '''
        
        if object:
            self._obj = object
        else:
            self._obj = tclass.New()
            
        self._in_set=0
            
        # Update the traits based on the values of the VTK object.
        if update:
            self.update_traits()
            
    def update_traits(self, obj=None, event=None):
        """Updates all the 'updateable' traits of the object.

        The method works by getting the current value from the wrapped
        VTK object.  `self._updateable_traits_` stores a tuple of
        tuples containing the trait name followed by the name of the
        get method to use on the wrapped VTK object.

        The `obj` and `event` parameters may be ignored and are not
        used in the function.  They exist only for compatibility with
        the VTK observer callback functions.
        
        """
        if self._in_set:
            return
        if not hasattr(self, '_updateable_traits_'):
            return
        self._in_set = self.DOING_UPDATE
        obj = self._obj

        for name, getter in self._updateable_traits_:
            try:
                val = getattr(obj, getter)()
            except (AttributeError, TypeError):
                pass
            else:
                setattr(self, name, val)
        self._in_set = 0
    
    def _do_change(self, method, val, force_update=False):
        """This is called by the various traits when they change in
        order to update the underlying VTK object.

        Parameters
        ----------

        - method: `method`

          The method to invoke on the VTK object when called.

        - val: `Any`

          Argument to the method.

        - force_update: `bool` (default: False)

          If True, `update_traits` is always called at the end.
          
        """
        if self._in_set == self.DOING_UPDATE:
            return        
        obj = self._obj
        self._in_set += 1
        
        try:
            method(val)
        except TypeError:
            if hasattr(val, '__len__'):
                method(*val)
            else:
                raise
        self._in_set -= 1
        if force_update:
            self.update_traits()
            
    def _wrap_call(self, itk_method, *args):
        """This method allows us to safely call a ITK method without
        calling `update_traits` during the call.  This method is
        therefore used to wrap any 'Set' call on a ITK object.

        The method returns the output of the vtk_method call.

        Parameters
        ----------

        - itk_method: `method`

          The method to invoke safely.

        - args: `Any`

          Argument to be passed to the method.

        """
        _obj = self._obj
        self._in_set += 1
        ret = itk_method(*args)
        self._in_set -= 1
        self.update_traits()
        return ret

            
if __name__=="__main__":
   
    titkbase(int).configure_traits()